package com.feng.study.pay;
import okhttp3.*;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

public class WeChatPay02 {

    private static final String API_KEY = "your_api_key"; // 商户API密钥
    private static final String MCH_ID = "your_mch_id"; // 商户号
    private static final String APP_ID = "your_app_id"; // 公众账号ID或应用APPID
    private static final String CERT_PATH = "path_to_your_cert_file"; // 商户证书文件路径

    private static final MediaType MEDIA_TYPE_XML = MediaType.parse("application/xml; charset=utf-8");

    private OkHttpClient client = new OkHttpClient();

    /**
     * 付款到零钱
     *
     * @param openid   用户openid
     * @param amount   付款金额，单位为分
     * @param tradeNo  商户订单号
     * @param spbillIp 终端IP
     * @return 返回微信支付服务器的响应结果
     */
    public String transferMoney(String openid, int amount, String tradeNo, String spbillIp) throws IOException, NoSuchAlgorithmException {
        // 构造请求参数
        Map<String, String> reqData = new HashMap<>();
        reqData.put("mch_appid", APP_ID);
        reqData.put("mchid", MCH_ID);
        reqData.put("nonce_str", generateNonceStr());
        reqData.put("partner_trade_no", tradeNo);
        reqData.put("openid", openid);
        reqData.put("check_name", "NO_CHECK");
        reqData.put("amount", String.valueOf(amount));
        reqData.put("desc", "Transfer money to user");
        reqData.put("spbill_create_ip", spbillIp);
        sign(reqData); // 对请求参数进行签名

        // 将请求参数转换为XML格式
        String requestXml = generateXML(reqData);

        // 创建请求对象
        Request request = new Request.Builder()
                .url("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers")
                .post(RequestBody.create(MEDIA_TYPE_XML, requestXml))
                .build();

        // 发送请求并获取响应结果
        Response response = client.newCall(request).execute();
        if (!response.isSuccessful()) {
            throw new IOException("Unexpected code " + response);
        }
        return response.body().string();
    }

    /**
     * 对请求参数进行签名
     *
     * @param reqData 请求参数
     */
    private void sign(Map<String, String> reqData) throws NoSuchAlgorithmException {
        StringBuilder sb = new StringBuilder();
        for (String key : reqData.keySet()) {
            String value = reqData.get(key);
            if (value != null && !value.isEmpty()) {
                sb.append(key).append("=").append(value).append("&");
            }
        }
        sb.append("key=").append(API_KEY);
        String sign = encryptMD5(sb.toString()).toUpperCase();
        reqData.put("sign", sign);
    }

    /**
     * 生成随机字符串
     *
     * @return 返回长度为32的随机字符串
     */
    private String generateNonceStr() {
        return java.util.UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 将请求参数转换为XML格式
     *
     * @param reqData 请求参数
     * @return 返回XML格式的请求参数
     */
    private String generateXML(Map<String, String> reqData) {
        StringBuilder sb = new StringBuilder("<xml>");
        for (Map.Entry<String, String> entry : reqData.entrySet()) {
            sb.append('<').append(entry.getKey()).append('>');
            sb.append(entry.getValue());
            sb.append("</").append(entry.getKey()).append('>');
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 计算MD5摘要
     *
     * @param data 要加密的字符串
     * @return 加密后的字符串
     */
    private String encryptMD5(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(data.getBytes());
        byte[] digest = md.digest();

        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        return sb.toString();
    }
}
